from django.conf import settings
from django.forms.models import model_to_dict
from django.db.models import Avg, Sum, Count, Max, Min, Q, F
from django_filters import *
from django_filters.rest_framework import DjangoFilterBackend, FilterSet

from rest_framework import viewsets
from rest_framework import serializers
from rest_framework import versioning
from rest_framework.response import Response
from rest_framework.serializers import *
from rest_framework.validators import UniqueValidator, UniqueTogetherValidator  # 验证器
from rest_framework.filters import SearchFilter, OrderingFilter

from iClouds.apidev import has_Reqsn_Callme, filter_views
from iClouds.Permissions import (
    OR,
    AllPermissions,
    MyPermissions,
    BoxPermissions,
    WeChatPermissions,
    BarPermissions,
)
from iClouds.Authentication import (
    MyJWTAuthentication,
    BoxJWTAuthentication,
    WeChatJWTAuthentication,
    BarJWTAuthentication,
)

from mysqldb.models import *
from mysqldb.serializers import ListDjangoFilterBackend
from ReportManager.serializers import FsygShopreqsnListSerializer


class NoneSerializer(serializers.Serializer):
    """无序列化"""

    class Meta:
        fields = "__all__"


class AllinpayCallmeConfSerializer(serializers.ModelSerializer):
    """呼叫配置"""

    id = IntegerField(label="ID", read_only=True)
    # compare = CharField(allow_blank=True, allow_null=True, help_text="运算符")
    # value = CharField(allow_blank=True, allow_null=True, help_text="阈值")
    pid = IntegerField(allow_null=True, help_text="场所ID")
    status = IntegerField(allow_null=True, help_text="状态")
    timeout = IntegerField(allow_null=True, default=60, help_text="超时")
    reward = IntegerField(allow_null=True, required=False, help_text="接单奖励")
    redemption = IntegerField(allow_null=True, required=False, help_text="评价奖励")
    dispatch = ChoiceField(
        choices=((0, "前台应答"), (1, "随机派单"), (2, "轮流派单"), (3, "抢单模式"), (4, "固定指派")),
        help_text="派单模式",
    )
    name = CharField(allow_blank=True, allow_null=True, help_text="名称")
    remarks = CharField(
        allow_blank=True, allow_null=True, required=False, help_text="备注"
    )

    le0 = IntegerField(default=0, help_text="员工接单奖励")
    le1 = IntegerField(default=0, help_text="员工差评奖励")
    le2 = IntegerField(default=0, help_text="员工一般奖励")
    le3 = IntegerField(default=0, help_text="员工好评奖励")
    le4 = IntegerField(default=0, help_text="员工优秀奖励")
    le5 = IntegerField(default=0, help_text="会员评价奖励")

    appurl = CharField(allow_blank=True, required=False, help_text="小程序url")

    aorders = SerializerMethodField()
    evaluate = SerializerMethodField()

    class Meta:
        model = AllinpayCallmeConf
        fields = [
            "id",
            "name",
            "pid",
            "status",
            "remarks",
            "timeout",
            "reward",
            "redemption",
            "dispatch",
            "aorders",
            "evaluate",
            "le0",
            "le1",
            "le2",
            "le3",
            "le4",
            "le5",
            "appurl",
        ]
        validators = [
            UniqueTogetherValidator(
                queryset=AllinpayCallmeConf.objects.all(), fields=("name", "pid")
            )
        ]

    def get_aorders(self, attr):
        try:
            r = AllinpayRawardList.objects.get(id=attr.reward)
        except BaseException as err:
            return None
        else:
            return AllinpayRawardListSerializer(r).data

    def get_evaluate(self, attr):
        try:
            r = AllinpayRawardModel.objects.get(id=attr.redemption)
        except BaseException as err:
            return None
        else:
            return AllinpayRawardModelSerializer(r).data


class AllinpayRawardListSerializer(serializers.ModelSerializer):
    """奖励项"""

    id = IntegerField(label="ID", read_only=True)
    pid = IntegerField(allow_null=True, required=True, help_text="场所ID")
    raid = IntegerField(allow_null=True, required=False, help_text="模板ID")
    integral = IntegerField(
        allow_null=True, max_value=2147483647, min_value=-2147483648, required=True
    )
    intetype = IntegerField(
        allow_null=True, max_value=2147483647, min_value=-2147483648, required=True
    )
    name = CharField(allow_blank=True, allow_null=True, max_length=255, required=False)

    tn = SerializerMethodField()

    class Meta:
        model = AllinpayRawardList
        fields = "__all__"

    def get_tn(self, attr):
        try:
            r = AllinpayIntegralList.objects.get(id=attr.intetype)
        except BaseException as err:
            return ""
        else:
            return r.name


class AllinpayRawardModelSerializer(serializers.ModelSerializer):
    """奖励模板"""

    id = IntegerField(label="ID", read_only=True)
    pid = IntegerField(allow_null=True, required=True, help_text="场所ID")
    name = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="模板名称",
    )
    notes = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="备注信息",
    )
    status = IntegerField(
        allow_null=True, max_value=1, min_value=-0, default=1, help_text="状态"
    )

    raward = SerializerMethodField()

    class Meta:
        model = AllinpayRawardModel
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=AllinpayRawardModel.objects.all(), fields=("name", "pid")
            )
        ]

    def get_raward(self, attr):
        r = AllinpayRawardList.objects.filter(raid=attr.id)
        return AllinpayRawardListSerializer(r, many=True).data


# print(repr(AllinpayRawardListSerializer()))


class AllinpayCallmePostSerializer(serializers.ModelSerializer):
    """应答配置"""

    id = IntegerField(label="ID", read_only=True)
    pid = IntegerField(help_text="场所ID")
    sid = IntegerField(help_text="绑定原始ID")
    cid = IntegerField(help_text="绑定呼叫配置ID")
    status = IntegerField(default=0, help_text="状态")

    class Meta:
        model = AllinpayCallmePost
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=AllinpayCallmePost.objects.all(), fields=("sid", "cid", "pid")
            )
        ]

    # def validate(self, attrs):
    #     attrs = dict(attrs)
    #     try:
    #         p = AllinpayPlaceList.objects.get(id=attrs.get("pid"), status=1)
    #         s = AllinpayStaffList.objects.get(id=attrs.get("sid"), status=1)
    #         c = AllinpayCallmeConf.objects.get(id=attrs.get("cid"), status=1)
    #         b = AllinpayPlacestaffList.objects.get(pid=p.id, sid=s.id, status=1)
    #     except AllinpayPlaceList.DoesNotExist as err:
    #         raise serializers.ValidationError({"pid": "场所参数错误"})
    #     except AllinpayStaffList.DoesNotExist as err:
    #         raise serializers.ValidationError({"sid": "员工参数错误"})
    #     except AllinpayCallmeConf.DoesNotExist as err:
    #         raise serializers.ValidationError({"sid": "呼叫配置参数错误"})
    #     except AllinpayPlacestaffList.DoesNotExist as err:
    #         raise serializers.ValidationError({"pid,sid": "员工在职参数错误"})

    #     return attrs


class AllinpayCallmeListSerializer(serializers.ModelSerializer):
    """呼叫列表"""

    id = IntegerField(read_only=True)
    reqsn = CharField(read_only=True, help_text="呼叫订单号")
    pid = IntegerField(help_text="场所ID")
    rtype = IntegerField(help_text="呼叫类型")
    source = CharField(allow_blank=True, allow_null=True, help_text="呼叫机号")
    area = CharField(
        allow_blank=True, allow_null=True, required=False, help_text="区域(房号)"
    )
    notes = CharField(allow_blank=True, allow_null=True, required=False, help_text="备注")
    current = DateTimeField(allow_null=True, required=False, help_text="创建时间")
    target = IntegerField(allow_null=True, required=False, help_text="呼叫目标ID")
    timeout = IntegerField(allow_null=True, default=0, help_text="超时时间 (秒)")
    overtime = IntegerField(allow_null=True, required=False, help_text="是否超时(0未超时 or 1 超时)")
    vipid = IntegerField(allow_null=True, default=0, help_text="会员ID")
    status = IntegerField(allow_null=True, required=False, help_text="状态")
    answer = IntegerField(allow_null=True, required=False, help_text="应答者ID")
    antime = DateTimeField(allow_null=True, required=False, help_text="应答时间")
    retime = DateTimeField(allow_null=True, required=False, help_text="接单时间")
    complete = DateTimeField(allow_null=True, required=False, help_text="完成时间")
    evaluate = DateTimeField(allow_null=True, required=False, help_text="评价时间")
    star = CharField(allow_blank=True, allow_null=True, required=False, help_text="评价")
    localid = IntegerField(allow_null=True, required=False, help_text="本地ID(停用)")

    le0 = IntegerField(default=0, help_text="员工接单奖励")
    le1 = IntegerField(default=0, help_text="员工评价奖励")
    le2 = IntegerField(default=0, help_text="会员评价奖励")
    le1k = CharField(
        allow_blank=True,
        allow_null=True,
        required=False,
        help_text="员工评价奖励字段名(le1-le5)",
    )

    bem = CharField(
        allow_blank=True, allow_null=True, required=False, help_text="备注(凡商销售单号)"
    )

    placeName = SerializerMethodField()
    rtypesName = SerializerMethodField()
    memberName = SerializerMethodField()
    answerName = SerializerMethodField()
    targetName = SerializerMethodField()
    starName = SerializerMethodField()
    shopName = SerializerMethodField()

    class Meta:
        model = AllinpayCallmeList
        fields = "__all__"

    def get_placeName(self, attr):
        try:
            instance = AllinpayPlaceList.objects.get(id=attr.pid)
        except BaseException as err:
            return None
        return model_to_dict(instance)

    def get_rtypesName(self, attr):
        try:
            instance = AllinpayCallmeConf.objects.get(id=attr.rtype)
        except BaseException as err:
            return None
        return AllinpayCallmeConfSerializer(instance).data

    def get_memberName(self, attr):
        try:
            instance = AllinpayMemberList.objects.get(localid=attr.vipid)
        except BaseException as err:
            return None
        return model_to_dict(instance)

    def get_answerName(self, attr):
        try:
            instance = AllinpayStaffList.objects.get(id=attr.answer)
        except BaseException as err:
            return None
        return model_to_dict(instance)

    def get_targetName(self, attr):
        try:
            instance = AllinpayStaffList.objects.get(id=attr.target)
        except BaseException as err:
            return None
        return model_to_dict(instance)

    def get_starName(self, attr):
        try:
            instance = AllinpayRawardList.objects.get(id=attr.star)
        except BaseException as err:
            return None
        return AllinpayRawardListSerializer(instance).data

    def get_shopName(self, attr):
        try:
            instance = FsygShopreqsnList.objects.get(id=attr.bem)
        except BaseException as err:
            return None
        else:
            return FsygShopreqsnListSerializer(instance).data


class AllinpayCallmeCreatSerializer(serializers.ModelSerializer):
    """创建呼叫"""

    id = IntegerField(read_only=True)
    pid = IntegerField(help_text="场所ID")
    rtype = IntegerField(help_text="呼叫类型")
    source = CharField(allow_blank=True, allow_null=True, help_text="呼叫机号")
    vipid = IntegerField(allow_null=True, required=False, help_text="会员ID")
    target = IntegerField(allow_null=True, required=False, help_text="呼叫目标ID")
    notes = CharField(allow_blank=True, allow_null=True, required=False, help_text="备注")

    conf = SerializerMethodField()
    staffName = SerializerMethodField()

    class Meta:
        model = AllinpayCallmeList
        fields = ["id", "pid", "rtype", "source", "vipid", "target", "notes", "conf","staffName"]

    def get_conf(self, attr):
        try:
            r = AllinpayCallmeConf.objects.get(id=attr.rtype)
        except BaseException as err:
            return None
        else:
            return AllinpayCallmeConfSerializer(r).data
    def get_staffName(self, attr):
        try:
            r = AllinpayStaffList.objects.get(id=attr.target)
        except BaseException as err:
            return ""
        else:
            return r.basename    
    def validate(self, attrs):
        try:
            conf = AllinpayCallmeConf.objects.get(id=attrs["rtype"], pid=attrs["pid"])
            place = AllinpayPlaceList.objects.get(id=attrs["pid"], status=1)
            if attrs.get("target"):
                post = AllinpayCallmePost.objects.get(pid=place.id,sid=attrs["target"],cid=conf.id,status=1)
            # AllinpayHardwareList.objects.get(pcname=attrs["source"], pid=attrs["pid"])
            # AllinpayMemberList.objects.get(id=attrs["vipid"], pid=attrs["pid"])
        except AllinpayCallmeConf.DoesNotExist as err:
            raise serializers.ValidationError("加载呼叫配置错误")
        except AllinpayPlaceList.DoesNotExist as err:
            raise serializers.ValidationError("加载场所参数错误")
        except AllinpayCallmePost.DoesNotExist as err:
            raise serializers.ValidationError("该用户暂停服务")        
        except AllinpayHardwareList.DoesNotExist as err:
            raise serializers.ValidationError("呼叫终端错误")
        except AllinpayMemberList.DoesNotExist as err:
            raise serializers.ValidationError("呼叫会员错误")
        except BaseException as err:
            raise serializers.ValidationError({"未知错误", err})
        else:
            if conf.reward == 4 and not attrs.get("target"):
                raise serializers.ValidationError("呼叫目标不存在")
        return attrs


class AllinpayCallmeReqsnPostSerializer(serializers.ModelSerializer):
    """派单"""

    target = IntegerField(help_text="呼叫目标ID")

    # status = IntegerField(default=2, help_text="状态")
    # answer = IntegerField(help_text="呼叫目标ID")
    # antime =  CharField(allow_blank=True, allow_null=True, required=False, help_text="备注")
    class Meta:
        model = AllinpayCallmeList
        fields = ["target"]


class AllinpayCallmeReqsnOverSerializer(serializers.ModelSerializer):
    """结单"""

    status = IntegerField(default=4, help_text="状态")

    class Meta:
        model = AllinpayCallmeList
        fields = ["status"]


class AllinpayCallmeReqsnExcetSerializer(serializers.ModelSerializer):
    """评价"""

    le1 = IntegerField(help_text="评价呼叫记录(评价分值)")
    le1k = CharField(allow_blank=True, allow_null=True, help_text="评价字段(le1-le5)")

    class Meta:
        model = AllinpayCallmeList
        fields = ["le1", "le1k"]
